/**
 * 必要的Polyfills集合
 * 为旧版浏览器提供现代API支持
 */

// Promise polyfill (for IE)
if (typeof Promise === 'undefined') {
    window.Promise = function(executor) {
        var self = this;
        self.state = 'pending';
        self.value = undefined;
        self.handlers = [];
        
        function resolve(result) {
            if (self.state === 'pending') {
                self.state = 'fulfilled';
                self.value = result;
                self.handlers.forEach(handle);
                self.handlers = null;
            }
        }
        
        function reject(error) {
            if (self.state === 'pending') {
                self.state = 'rejected';
                self.value = error;
                self.handlers.forEach(handle);
                self.handlers = null;
            }
        }
        
        function handle(handler) {
            if (self.state === 'pending') {
                self.handlers.push(handler);
            } else {
                if (self.state === 'fulfilled' && typeof handler.onFulfilled === 'function') {
                    handler.onFulfilled(self.value);
                }
                if (self.state === 'rejected' && typeof handler.onRejected === 'function') {
                    handler.onRejected(self.value);
                }
            }
        }
        
        this.then = function(onFulfilled, onRejected) {
            return new Promise(function(resolve, reject) {
                handle({
                    onFulfilled: function(result) {
                        try {
                            resolve(onFulfilled ? onFulfilled(result) : result);
                        } catch (ex) {
                            reject(ex);
                        }
                    },
                    onRejected: function(error) {
                        try {
                            resolve(onRejected ? onRejected(error) : error);
                        } catch (ex) {
                            reject(ex);
                        }
                    }
                });
            });
        };
        
        this.catch = function(onRejected) {
            return this.then(null, onRejected);
        };
        
        try {
            executor(resolve, reject);
        } catch (ex) {
            reject(ex);
        }
    };
    
    Promise.resolve = function(value) {
        return new Promise(function(resolve) {
            resolve(value);
        });
    };
    
    Promise.reject = function(reason) {
        return new Promise(function(resolve, reject) {
            reject(reason);
        });
    };
    
    Promise.all = function(promises) {
        return new Promise(function(resolve, reject) {
            var results = [];
            var remaining = promises.length;
            
            if (remaining === 0) {
                resolve(results);
                return;
            }
            
            promises.forEach(function(promise, index) {
                Promise.resolve(promise).then(function(value) {
                    results[index] = value;
                    remaining--;
                    if (remaining === 0) {
                        resolve(results);
                    }
                }, reject);
            });
        });
    };
}

// Fetch polyfill (简化版)
if (typeof fetch === 'undefined') {
    window.fetch = function(url, options) {
        return new Promise(function(resolve, reject) {
            var xhr = new XMLHttpRequest();
            options = options || {};
            
            xhr.open(options.method || 'GET', url);
            
            // 设置请求头
            if (options.headers) {
                for (var key in options.headers) {
                    xhr.setRequestHeader(key, options.headers[key]);
                }
            }
            
            xhr.onload = function() {
                var response = {
                    ok: xhr.status >= 200 && xhr.status < 300,
                    status: xhr.status,
                    statusText: xhr.statusText,
                    text: function() {
                        return Promise.resolve(xhr.responseText);
                    },
                    json: function() {
                        return Promise.resolve(JSON.parse(xhr.responseText));
                    },
                    arrayBuffer: function() {
                        return Promise.resolve(xhr.response);
                    }
                };
                resolve(response);
            };
            
            xhr.onerror = function() {
                reject(new Error('Network error'));
            };
            
            if (options.body) {
                xhr.send(options.body);
            } else {
                xhr.send();
            }
        });
    };
}

// Object.assign polyfill
if (typeof Object.assign !== 'function') {
    Object.assign = function(target) {
        if (target == null) {
            throw new TypeError('Cannot convert undefined or null to object');
        }
        
        var to = Object(target);
        
        for (var index = 1; index < arguments.length; index++) {
            var nextSource = arguments[index];
            
            if (nextSource != null) {
                for (var nextKey in nextSource) {
                    if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                        to[nextKey] = nextSource[nextKey];
                    }
                }
            }
        }
        return to;
    };
}

// Array.from polyfill
if (!Array.from) {
    Array.from = function(arrayLike, mapFn, thisArg) {
        var C = this;
        var items = Object(arrayLike);
        
        if (arrayLike == null) {
            throw new TypeError('Array.from requires an array-like object - not null or undefined');
        }
        
        var mapFunction = mapFn === undefined ? undefined : mapFn;
        if (typeof mapFunction !== 'undefined' && typeof mapFunction !== 'function') {
            throw new TypeError('Array.from: when provided, the second argument must be a function');
        }
        
        var len = parseInt(items.length);
        var A = typeof C === 'function' ? Object(new C(len)) : new Array(len);
        var k = 0;
        var kValue;
        
        while (k < len) {
            kValue = items[k];
            if (mapFunction) {
                A[k] = typeof thisArg === 'undefined' ? mapFunction(kValue, k) : mapFunction.call(thisArg, kValue, k);
            } else {
                A[k] = kValue;
            }
            k += 1;
        }
        A.length = len;
        return A;
    };
}

// Array.includes polyfill
if (!Array.prototype.includes) {
    Array.prototype.includes = function(searchElement, fromIndex) {
        if (this == null) {
            throw new TypeError('"this" is null or not defined');
        }
        
        var o = Object(this);
        var len = parseInt(o.length) || 0;
        
        if (len === 0) {
            return false;
        }
        
        var n = parseInt(fromIndex) || 0;
        var k;
        
        if (n >= 0) {
            k = n;
        } else {
            k = len + n;
            if (k < 0) {
                k = 0;
            }
        }
        
        function sameValueZero(x, y) {
            return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
        }
        
        while (k < len) {
            if (sameValueZero(o[k], searchElement)) {
                return true;
            }
            k++;
        }
        
        return false;
    };
}

// String.includes polyfill
if (!String.prototype.includes) {
    String.prototype.includes = function(search, start) {
        if (typeof start !== 'number') {
            start = 0;
        }
        
        if (start + search.length > this.length) {
            return false;
        } else {
            return this.indexOf(search, start) !== -1;
        }
    };
}

// requestAnimationFrame polyfill
if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = function(callback) {
        return setTimeout(callback, 1000 / 60);
    };
}

if (!window.cancelAnimationFrame) {
    window.cancelAnimationFrame = function(id) {
        clearTimeout(id);
    };
}

// CustomEvent polyfill
if (typeof window.CustomEvent !== 'function') {
    function CustomEvent(event, params) {
        params = params || { bubbles: false, cancelable: false, detail: undefined };
        var evt = document.createEvent('CustomEvent');
        evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
        return evt;
    }
    
    CustomEvent.prototype = window.Event.prototype;
    window.CustomEvent = CustomEvent;
}

// classList polyfill (简化版)
if (!('classList' in document.createElement('_'))) {
    (function(view) {
        if (!('Element' in view)) return;
        
        var classListProp = 'classList',
            protoProp = 'prototype',
            elemCtrProto = view.Element[protoProp],
            objCtr = Object,
            strTrim = String[protoProp].trim || function() {
                return this.replace(/^\s+|\s+$/g, '');
            },
            arrIndexOf = Array[protoProp].indexOf || function(item) {
                var i = 0, len = this.length;
                for (; i < len; i++) {
                    if (i in this && this[i] === item) {
                        return i;
                    }
                }
                return -1;
            };
        
        var DOMTokenList = function(el) {
            this.el = el;
            var classes = el.className.replace(/^\s+|\s+$/g, '').split(/\s+/);
            for (var i = 0; i < classes.length; i++) {
                this.push(classes[i]);
            }
            this._updateClassName = function() {
                el.className = this.toString();
            };
        };
        
        var tokenListProto = DOMTokenList[protoProp] = [];
        
        tokenListProto.item = function(index) {
            return this[index] || null;
        };
        
        tokenListProto.contains = function(token) {
            token += '';
            return arrIndexOf.call(this, token) !== -1;
        };
        
        tokenListProto.add = function() {
            var tokens = arguments;
            var i = 0;
            var l = tokens.length;
            var token;
            var updated = false;
            do {
                token = tokens[i] + '';
                if (arrIndexOf.call(this, token) === -1) {
                    this.push(token);
                    updated = true;
                }
            } while (++i < l);
            
            if (updated) {
                this._updateClassName();
            }
        };
        
        tokenListProto.remove = function() {
            var tokens = arguments;
            var i = 0;
            var l = tokens.length;
            var token;
            var updated = false;
            var index;
            do {
                token = tokens[i] + '';
                index = arrIndexOf.call(this, token);
                while (index !== -1) {
                    this.splice(index, 1);
                    updated = true;
                    index = arrIndexOf.call(this, token);
                }
            } while (++i < l);
            
            if (updated) {
                this._updateClassName();
            }
        };
        
        tokenListProto.toggle = function(token, force) {
            token += '';
            
            var result = this.contains(token),
                method = result ? force !== true && 'remove' : force !== false && 'add';
            
            if (method) {
                this[method](token);
            }
            
            if (force === true || force === false) {
                return force;
            } else {
                return !result;
            }
        };
        
        tokenListProto.toString = function() {
            return this.join(' ');
        };
        
        if (objCtr.defineProperty) {
            var classListPropDesc = {
                get: function() {
                    return new DOMTokenList(this);
                },
                enumerable: true,
                configurable: false
            };
            try {
                objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
            } catch (ex) {
                if (ex.number === -0x7FF5EC54) {
                    classListPropDesc.enumerable = false;
                    objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
                }
            }
        }
    }(window));
}

console.log('Polyfills 加载完成');
